home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / network / ka9q / ka9q_src.arc / ICMPCMD.C < prev    next >
C/C++ Source or Header  |  1988-07-28  |  5KB  |  241 lines

  1. /* ICMP-related user commands */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "icmp.h"
  5. #include "mbuf.h"
  6. #include "netuser.h"
  7. #include "internet.h"
  8. #include "timer.h"
  9. #include "ping.h"
  10.  
  11. int pingflag = 1;    /* DG2KK */
  12.  
  13. int
  14. doicmpstat()
  15. {
  16.     extern struct icmp_errors icmp_errors;
  17.     extern struct icmp_stats icmp_stats;
  18.     extern char *icmptypes[];
  19.     register int i;
  20.  
  21.     printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
  22.      icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
  23.      icmp_errors.bdcsts);
  24.     printf("type  rcvd  sent\n");
  25.     for(i=0;i<ICMP_TYPES;i++){
  26.         if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
  27.             continue;
  28.         printf("%-6u%-6u%-6u",i,icmp_stats.input[i],
  29.             icmp_stats.output[i]);
  30.         if(icmptypes[i] != NULLCHAR)
  31.             printf("  %s",icmptypes[i]);
  32.         printf("\n");
  33.     }
  34.     return 0;
  35. }
  36.  
  37. /* Hash table list heads */
  38. struct ping *ping[PMOD];
  39.  
  40. /* 1 Hz counter for generating seq numbers */
  41. static int16 iclk;
  42.  
  43. /* Increment counter -- called by low level clock tick */
  44. icmpclk()
  45. {
  46.     iclk++;
  47. }
  48.  
  49. /* Send ICMP Echo Request packets */
  50. doping(argc,argv)
  51. int argc;
  52. char *argv[];
  53. {
  54.     int32 dest;
  55.     struct ping *add_ping(),*pp1;
  56.     register struct ping *pp;
  57.     void ptimeout();
  58.     register int16 count;
  59.     int16 hval,hash_ping();
  60.     int i;
  61.     char *inet_ntoa();
  62.  
  63.     if(argc < 2){
  64.         printf("Host                Sent    Rcvd   %%   Avg RTT\n");
  65.         for(i=0;i<PMOD;i++){
  66.             for(pp = ping[i];pp != NULLPING;pp = pp->next){
  67.                 printf("%-16s",inet_ntoa(pp->remote));
  68.                 printf("%8ld%8ld",pp->count,pp->echoes);
  69.                 printf("%4ld%10ld\n",
  70.                  (long)pp->echoes * 100 / pp->count,
  71.                  pp->echoes != 0 ? 
  72.                  (long)pp->ttotal * MSPTICK / pp->echoes : 0);
  73.             }
  74.         }
  75.         return 0;
  76.     }
  77.     if(strcmp(argv[1],"clear") == 0){
  78.         for(i=0;i<PMOD;i++){
  79.             for(pp = ping[i];pp != NULLPING;pp = pp1){
  80.                 pp1 = pp->next;
  81.                 del_ping(pp);
  82.             }
  83.         }
  84.         return 0;
  85.     }
  86.     /* DG2KK: added ping ON/OFF.
  87.      * "ping off" stops echo replies from being sent when an echo request
  88.      * is received.
  89.      */
  90.     if(strcmp(argv[1],"on") == 0){
  91.         pingflag = 1;
  92.         return 0;
  93.     }
  94.     if(strcmp(argv[1],"off") == 0){
  95.         pingflag = 0;
  96.         return 0;
  97.     }
  98.  
  99.     if((dest = resolve(argv[1])) == 0){
  100.         printf("Host %s unknown\n",argv[1]);
  101.         return 1;
  102.     }
  103.     /* See if dest is already in table */
  104.     hval = hash_ping(dest);
  105.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next){
  106.         if(pp->remote == dest){
  107.             break;
  108.         }
  109.     }
  110.     if(argc > 2){
  111.         /* Inter-ping time is specified; set up timer structure */
  112.         /* DG2KK: inter-ping time must be at least 300 seconds! */
  113.         if(atoi(argv[2]) < 300){
  114.             printf("Inter-ping time must be at least 300 s!\n");
  115.             return -1;
  116.         }
  117.         if(pp == NULLPING)
  118.             pp = add_ping(dest);
  119.         pp->timer.start = atoi(argv[2]);
  120.         pp->timer.func = ptimeout;
  121.         pp->timer.arg = (char *)pp;
  122.         pp->remote = dest;
  123.         start_timer(&pp->timer);
  124.         pp->count++;
  125.     }
  126.     pingem(dest,iclk);
  127.     return 0;
  128. }
  129.  
  130. /* Called by ping timeout */
  131. void
  132. ptimeout(p)
  133. char *p;
  134. {
  135.     register struct ping *pp;
  136.  
  137.     /* Send another ping */
  138.     pp = (struct ping *)p;
  139.     pp->count++;
  140.     pingem(pp->remote,iclk);
  141.     start_timer(&pp->timer);
  142. }
  143. /* Send ICMP Echo Request packet */
  144. static
  145. pingem(dest,seq)
  146. int32 dest;
  147. int16 seq;
  148. {
  149.     struct mbuf *bp,*htonicmp();
  150.     struct icmp icmp;
  151.  
  152.     icmp_stats.output[ECHO]++;
  153.     icmp.type = ECHO;
  154.     icmp.code = 0;
  155.     icmp.args.echo.seq = seq;
  156.     icmp.args.echo.id = 0;
  157.     bp = htonicmp(&icmp,NULLBUF);
  158.     ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
  159.     return 0;
  160. }
  161.  
  162. /* Called with incoming Echo Reply packet */
  163. int
  164. echo_proc(source,dest,icmp)
  165. int32 source,dest;
  166. struct icmp *icmp;
  167. {
  168.     register struct ping *pp;
  169.     int16 hval,hash_ping();
  170.     int16 rtt;
  171.     char *inet_ntoa();
  172.  
  173.     rtt = iclk - icmp->args.echo.seq;
  174.     hval = hash_ping(source);
  175.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
  176.         if(pp->remote == source)
  177.             break;
  178.     if(pp == NULLPING){
  179.         printf("%s: echo reply id %d seq %d, %lu ms\n",
  180.          inet_ntoa(source),
  181.          icmp->args.echo.id,icmp->args.echo.seq,
  182.          (long)rtt * MSPTICK);
  183.          fflush(stdout);
  184.     } else {
  185.         /* Repeated poll, just keep stats */
  186.         pp->ttotal += rtt;
  187.         pp->echoes++;
  188.     }
  189. }
  190. static
  191. int16
  192. hash_ping(dest)
  193. int32 dest;
  194. {
  195.     int16 hval;
  196.  
  197.     hval = (hiword(dest) ^ loword(dest)) % PMOD;
  198.     return hval;
  199. }
  200. /* Add entry to ping table */
  201. static
  202. struct ping *
  203. add_ping(dest)
  204. int32 dest;
  205. {
  206.     struct ping *pp;
  207.     int16 hval,hash_ping();
  208.  
  209.     pp = (struct ping *)calloc(1,sizeof(struct ping));
  210.     if(pp == NULLPING)
  211.         return NULLPING;
  212.  
  213.     hval = hash_ping(dest);
  214.     pp->prev = NULLPING;
  215.     pp->next = ping[hval];
  216.     if(pp->next != NULLPING)
  217.         pp->next->prev = pp;
  218.     ping[hval] = pp;
  219.     return pp;
  220. }
  221. /* Delete entry from ping table */
  222. static
  223. del_ping(pp)
  224. struct ping *pp;
  225. {
  226.     int16 hval,hash_ping();
  227.  
  228.     stop_timer(&pp->timer);
  229.  
  230.     if(pp->next != NULLPING)
  231.         pp->next->prev = pp->prev;
  232.     if(pp->prev != NULLPING) {
  233.         pp->prev->next = pp->next;
  234.     } else {
  235.         hval = hash_ping(pp->remote);
  236.         ping[hval] = pp->next;
  237.     }
  238.     free((char *)pp);    
  239. }
  240.  
  241.